package com.yunji.order.business;

import com.yunji.base.bo.BelongAmountModifyBO;
import com.yunji.base.cache.BaseCache;
import com.yunji.base.domain.BelongDO;
import com.yunji.base.dto.PayoutFieldDTO;
import com.yunji.base.service.BelongService;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.enums.business.TradeMode;
import com.yunji.common.enums.business.TradeTypes;
import com.yunji.common.enums.common.UserType;
import com.yunji.common.exception.ServiceException;
import com.yunji.common.model.domain.SiteDO;
import com.yunji.common.model.dto.LoginInfo;
import com.yunji.common.utils.StringUtils;
import com.yunji.common.utils.TimeUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.order.ali.AliPayoutRespDTO;
import com.yunji.order.bo.GetAuditApplyBO;
import com.yunji.order.bo.PayableBO;
import com.yunji.order.business.remote.AlibabaPayable;
import com.yunji.order.context.builder.PayoutBuilder;
import com.yunji.order.context.convert.PayoutConvert;
import com.yunji.order.context.convert.TradeConvert;
import com.yunji.order.domain.PayoutDO;
import com.yunji.order.domain.TradeDO;
import com.yunji.order.dto.PayoutCreateDTO;
import com.yunji.order.dto.PayoutPageDTO;
import com.yunji.order.emuns.PayMode;
import com.yunji.order.emuns.PayoutStatusEnum;
import com.yunji.order.service.PayoutService;
import com.yunji.order.service.TradeService;
import com.yunji.system.context.SystemContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * FileName:	PayoutBusiness.java
 * Copyright:	Copyright © 2024 云集互联 All Rights Reserved
 * Company:		云集互联
 * Create at:   2024-04-21 21:28:43
 * Description:
 * 用户提现业务处理
 * Modification History:
 * Author					Date					Version         Description
 * -------------------------------------------------------------------------------------
 * HuaAo0803@163.com	2024-04-21 21:28:43     1.0             1.0 Version
 */
@Component
public class PayoutBusiness extends BaseBusiness {
    @Resource
    private BelongService belongService;
    @Resource
    private PayoutService payoutService;
    @Resource
    private TradeService tradeService;
    @Resource
    private AlibabaPayable alibabaPayable;

    private static final String PAYOUT_MESSAGE = "{}用户已提现{}元";

    public List<PayoutDO> searchPayout(PayoutPageDTO payout) {
        List<PayoutDO> payoutDOS = payoutService.searchPayout(payout);
        for (PayoutDO payoutDO : payoutDOS) {
            if (UserType.SITE.getCode().equals(payoutDO.getUserType())) {
                BelongDO belong = BaseCache.getBelong(payoutDO.getBelongId());
                SiteDO site = BaseCache.getSite(belong.getSiteId());
                if (site != null)
                    payoutDO.setCreateName(site.getSiteName() + "-" + site.getSiteContacts());
            }
        }
        return payoutDOS;
    }

    /**
     * @param id 提现ID
     * @return Payout 提现信息
     * @Title selectPayout
     * 获取提现记录
     * @Date 2024-04-22 01:06:44.234
     */
    public PayoutDO selectPayout(Long id) {
        return payoutService.selectPayout(id);
    }

//     * @param payoutCode 提现流水号
//     * @return Payout 提现信息
//     * @Title selectPayout
//     * 获取提现记录
//     * @Date 2024-04-22 01:06:44.234
//     */
//    public PayoutDO selectPayout(String payoutCode) {
//        return payoutService.selectPayout(payoutCode);
//    }


    /**
     * @param vo 提现信息
     * @Title createPayout
     * 创建提现记录
     * @Date 2024-04-22 01:13:13.687
     */
    @Transactional
    public Long createPayout(PayoutCreateDTO vo) {
        logs.info("【创建提现】提现信息：{}", vo);
        LoginInfo info = SystemContext.getUser();
        ServiceException.throwException(BeanUtils.isNull(info.getBelongId()), "当前用户缺少账户信息");
        BelongDO belong = belongService.getById(info.getBelongId());
        BigDecimal payoutAmount = vo.getAmount();
        BigDecimal remainAmount = belong.getRemainAmount();
        logs.info("【创建提现】账户金额信息:{},剩余金额:{},提现金额:{}", belong, remainAmount, payoutAmount);
        ServiceException.throwException(payoutAmount.compareTo(remainAmount) > 0, "提现金额超过账户余额");
        PayoutDO payout = PayoutBuilder.builder().buildPayout(vo).buildUserInfo(info).build();
        payoutService.createPayout(payout);
        belongService.updateAccount(BelongAmountModifyBO.builder().belongId(belong.getBelongId())
                .frozenAmount(payoutAmount).remainAmount(payoutAmount.negate()).build());
        return payout.getPayoutId();
    }


    /**
     * @param ids 提现ID数组
     * @Title deletePayout
     * 删除提现记录
     * @Date 2024-04-22 01:06:50.678
     */
    public void deletePayout(Long[] ids) {
        payoutService.deletePayout(ids);
    }

    /**
     * @param payout 提现信息
     * @Title updatePayout
     * 更新提现记录
     * @Date 2024-04-22 01:06:47.205
     */
    public void updatePayout(PayoutDO payout) {
        payoutService.updatePayout(payout);
    }

    /**
     * @param id 提现ID数组
     * @Title closedPayout
     * 关闭提现申请
     * @Date 2024-04-22 01:06:50.678
     */
    public void closedPayout(Long id) {
        PayoutDO update = new PayoutDO();
        update.setPayoutId(id);
        update.setClosedTime(new Date());
        update.setApplyStatus(PayoutStatusEnum.CLOSED.getCode());
        payoutService.updatePayout(update);
    }


    public boolean rejectRefund(Long payoutId, String reason) {
        PayoutDO update = new PayoutDO();
        PayoutConvert.setAuditByLogin(update);
        update.setPayoutId(payoutId);
        update.setAuditRemark(reason);
        update.setApplyStatus(PayoutStatusEnum.REJECTED.getCode());
        PayoutDO payoutDO = payoutService.selectPayout(payoutId);
        BigDecimal amount = payoutDO.getAmount();
        belongService.updateAccount(BelongAmountModifyBO.builder().belongId(payoutDO.getBelongId()).frozenAmount(amount.negate())
                .remainAmount(amount).build());
        return payoutService.updatePayout(update);
    }

    /**
     * @param payoutId 提现ID
     * @Title auditPayout
     * 审核提现
     * @Date 2024-04-22 01:06:57.651
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean auditPayout(Long payoutId) {
        logs.info("【提现审核】提现ID:{}", payoutId);
        PayoutDO payoutDO = payoutService.selectPayout(payoutId);
        BigDecimal amount = payoutDO.getAmount();
        PayoutDO update = new PayoutDO();
        PayoutConvert.setAuditByLogin(update);
        update.setPayoutId(payoutId);
        String content = StringUtils.format(PAYOUT_MESSAGE, payoutDO.getPayoutRealName(), amount);
        PayableBO payable = new PayableBO(payoutDO.getPayoutAccount(), payoutDO.getPayoutCode(), content, payoutDO.getPayoutRealName(),
                amount.multiply(new BigDecimal("100")).longValue(), amount);
        AliPayoutRespDTO rs = alibabaPayable.payoutTrade(payable);
        update.setPayCode(rs.getAlipayOrderNo());
        update.setPayTime(TimeUtils.parseDate(rs.getTime()));
        if (rs.isSuccess()) {
            update.setApplyStatus(PayoutStatusEnum.DEPOSIT.getCode());
        } else {
            belongService.updateAccount(BelongAmountModifyBO.builder().belongId(payoutDO.getBelongId()).frozenAmount(amount.negate())
                    .remainAmount(amount).build());
            update.setApplyStatus(PayoutStatusEnum.FAILURE.getCode());
            update.setAuditRemark(rs.getErrorMsg());
        }
        return payoutService.updatePayout(update);
    }

    /**
     * @Title callback
     * @Desc 转账业务回调处理
     * @Date 2024-04-23 14:31:33.478
     */
    @Transactional(rollbackFor = Exception.class)
    public void callback(String payoutCode, String payCode, String payTime) {
        PayoutDO payout = payoutService.selectPayout(payoutCode);
        if(PayoutStatusEnum.DEPOSIT.getCode().equals(payout.getApplyStatus())){
            PayoutDO update = new PayoutDO();
            update.setPayoutId(payout.getPayoutId());
            update.setFinishTime(new Date());
            update.setApplyStatus(PayoutStatusEnum.SUCCESS.getCode());
            update.setPayCode(payCode);
            Date apiTime = TimeUtils.parseDate(payTime);
            update.setPayTime(apiTime);
            BigDecimal amount = payout.getAmount();
            TradeDO trade = TradeConvert.convertByPayout(payout);
            trade.setPayMode(PayMode.ALIPAY.getCode());
            trade.setTradeType(TradeTypes.PURSE_PAYOUTS.getCode());
            trade.setTradeMode(TradeMode.PAYOUT.getCode());
            trade.setApiCode(payCode);
            trade.setApiTime(apiTime);
            tradeService.createTrade(trade);
            logs.info("【转账回调】提现金额{}", amount);
            belongService.updateAccount(BelongAmountModifyBO.builder().belongId(payout.getBelongId()).cashAmount(amount)
                    .frozenAmount(amount.negate()).build());
            payoutService.updatePayout(update);
        }
    }

    /**
     * @return List<Payout>
     * @Title searchAuditPayout
     * 获取失败审核转账列表
     * @Date 2024-05-13 00:03:14.836
     */
    public List<PayoutDO> searchAuditPayout(GetAuditApplyBO bo) {
        return payoutService.searchAuditPayout(bo);
    }

    /*-------------------------------------搜索栏---------------------------------------*/

    /**
     * @param applyName 申请人过滤条件
     * @Title searchApplicantName
     * @Desc 申请人姓名匹配搜索
     * @Date 2024-09-07 11:02:11.778
     */
    public List<String> searchApplicantName(String applyName) {
//        Assert.isTrue((applyName.length() <= 6), "输入的申请人姓名不合规");
        PayoutFieldDTO param = new PayoutFieldDTO();
        param.setCreateName(applyName);
        param.setSearchFiled("p.create_name");
        List<String> list = payoutService.searchTableField(param);
        return BeanUtils.isNotNull(list) ? list : Collections.emptyList();
    }

    /**
     * @param applyPhone 申请人手机号
     * @Title searchApplicantPhone
     * @Desc 申请人手机号匹配搜索
     * @Date 2024-09-07 11:07:02.144
     */
    public List<String> searchApplicantPhone(String applyPhone) {
        Assert.isTrue((applyPhone.length() <= 11), "输入的申请人手机号不合规");
        PayoutFieldDTO param = new PayoutFieldDTO();
        param.setPhone(applyPhone);
        param.setSearchFiled("p.phone");
        List<String> list = payoutService.searchTableField(param);
        return BeanUtils.isNotNull(list) ? list : Collections.emptyList();
    }

}
